﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinForm_Halcon_ChePaiShiBie1
{
    public partial class Form1 : Form
    {
        HImage image;  // Halcon图像对象
        public Form1()
        {
            InitializeComponent();
            //hswc1.MouseWheel += (sender, e) =>
            //{
            //    hswc1.HSmartWindowControl_MouseWheel(sender, e);
            //};
            hswc1.MouseWheel += hswc1.HSmartWindowControl_MouseWheel;
            hswc2.MouseWheel += hswc2.HSmartWindowControl_MouseWheel;

            InitializeCamera();
        }
        // 声明全局变量
        private HWindow _hWindow; //显示窗体的引用
        private HFramegrabber _framegrabber; //相机采集器
        private bool _isGrabbing = false; //是否继续采集
        private Thread _grabThread; //声明一个实时采集图像的线程
        private void button1_Click(object sender, EventArgs e)
        {
            // 创建打开文件对话框
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "所有图片|*.bmp;*.jpg";  // 设置文件类型过滤器
            openFileDialog.Title = "加载图片";  // 设置对话框标题
            openFileDialog.RestoreDirectory = true;  // 关闭对话框后恢复之前的工作目录
            // 显示对话框并检查用户是否选择了文件
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                // 从选择的文件路径创建Halcon图像对象
                image = new HImage(openFileDialog.FileName);
                // 在Halcon窗口中显示图像
                hswc1.HalconWindow.DispObj(image);
                // 设置窗口显示为完整图像（自适应显示）
                hswc1.SetFullImagePart();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // 检测图像中文本行的方向角度（用于校正倾斜）
            // 参数说明：输入图像, 处理区域, 字符高度估计值, 角度下限(-50°), 角度上限(50°), 输出角度
            HOperatorSet.TextLineOrientation(image, image, 50, -50 * Math.PI / 180, 50 * Math.PI / 180, out HTuple angle);
            // 将检测到的角度转换为double类型（弧度制）
            double phi = angle;
            // 根据检测到的角度旋转图像（校正倾斜）
            // 参数说明：旋转角度(转换为度)，边缘填充模式
            HImage rotageImage = image.RotateImage(-phi / Math.PI * 180, "constant");
            // 增强图像对比度（突出细节）
            // 参数说明：掩模宽度, 掩模高度, 增强因子
            HImage ImageEmphasize = rotageImage.Emphasize(7, 7, 1);
            // 应用中值滤波（降噪）
            // 参数说明：滤波器类型, 滤波器尺寸, 边界处理模式
            HImage ImageMedian = rotageImage.MedianImage("circle", 5, "mirrored");
            // 将RGB图像分解为三个通道（红、绿、蓝）
            HImage redImage = ImageEmphasize.Decompose3(out HImage greenImage, out HImage blueImage);
            // 将RGB颜色空间转换为HSV颜色空间
            // 参数说明：输出H/S/V通道，转换模式
            HImage HImage = redImage.TransFromRgb(greenImage, blueImage, out HImage Simage, out HImage VImage, "hsv");
            //自动全局阈值分割
            HRegion region = Simage.BinaryThreshold("max_separability", "light",out HTuple usedThreshold);
            //开运算
            HRegion openRegion = region.OpeningCircle(2D);
            //连通区域
            HRegion connectedRegion = openRegion.Connection();
            //特征提取
            HRegion selectedRegion = connectedRegion.SelectShape( "area", "and", 32000D, 350000).SelectShape("rectangularity","and", 0.4, 1).SelectShape("row", "and", 0, 2780);
            //膨胀
            HRegion dilatedRegion = selectedRegion.DilationCircle(8D);
            //填充
            HRegion filledRegion = dilatedRegion.FillUp();
            //合并
            HRegion union1Region = filledRegion.Union1();
            //再次连通
            HRegion connectedRegion1 = union1Region.Connection();
            //转换为对应的有角度的矩形
            HRegion transRegion = connectedRegion1.ShapeTrans("rectangle2");
            //获取矩形的个数
            int number = transRegion.CountObj();
            HOperatorSet.GenEmptyObj(out HObject ROI);
            //通过循环判断长轴和短轴的比例
            for (int i = 1; i <= number; i++)
            {
                HRegion selectedObject = transRegion.SelectObj(i);
                //获取区域长轴与短轴的长度
                double ChangZhou = selectedObject.RegionFeatures("rect2_len1");
                double DuanZhou = selectedObject.RegionFeatures("rect2_len2");
                //获得区域长轴与短轴的比例
                double value = ChangZhou / DuanZhou;
                if (value > 2.8 && value < 4.3)
                {
                    //将符合条件的区域添加到ROI中
                    ROI = ROI.ConcatObj(selectedObject);
                }
                //读取ROI个数
                int number1 = ROI.CountObj();
                if (number1 == 1)
                {
                    HRegion hRegion = new HRegion(ROI);
                    //腐蚀
                    HRegion RegionErosion = hRegion.ErosionRectangle1(80, 80);
                    HImage ImageReduce = ImageMedian.ReduceDomain(RegionErosion);
                    HRegion region1 = ImageReduce.BinaryThreshold("max_separability", "light", out HTuple usedThreshold1);
                    HRegion ConnectedRegions1 = region1.Connection();
                    HRegion selectedRegion1 = ConnectedRegions1.SelectShape("contlength", "and", 105D, 150000).SelectShape("area", "and", 600, 100000);
                    HRegion dilatedRegion1 = selectedRegion1.DilationCircle(8d);
                    HRegion RegionUnion = dilatedRegion1.Union1();
                    HRegion ConnectedRegions3 = RegionUnion.Connection();
                    //求交集
                    HRegion RegionIntersection = ConnectedRegions3.Intersection(selectedRegion1);
                    HRegion SortedRegions = RegionIntersection.SortRegion("character", "true", "row");
                    //加载OMC文件
                    HOCRMlp hOCRMlp = new HOCRMlp();
                    hOCRMlp.ReadOcrClassMlp("charact.omc");
                    HTuple carNumber = hOCRMlp.DoOcrMultiClassMlp(SortedRegions, ImageReduce, out HTuple con);                    
                    string[] arrary = carNumber.ToSArr();
                    string str = "";
                    for (int i1 = 0; i1 < arrary.Length; i1++)
                    {
                        str += arrary[i1];
                    }
                    this.label4.Text = str;
                    // 清空Halcon窗口内容
                    this.hswc2.HalconWindow.ClearWindow();
                    // 显示旋转校正后的图像
                    this.hswc2.HalconWindow.DispObj(ImageReduce);

                    this.hswc2.SetFullImagePart();
                }
                else
                {
                    HRegion hRegionROI  = new HRegion(ROI);
                    HRegion ROI2 = hRegionROI.SelectShape("area", "and", 110000, 340000);
                    HRegion RegionErosion = hRegionROI.ErosionRectangle1(80, 120);
                    HImage ImageReduce = ImageMedian.ReduceDomain(RegionErosion);
                    HRegion region1 = ImageReduce.BinaryThreshold("max_separability", "light", out HTuple usedThreshold1);
                    HRegion ConnectedRegions1 = region1.Connection();
                    HRegion selectedRegion1 = ConnectedRegions1.SelectShape("contlength", "and", 105D, 150000).SelectShape("area", "and", 600, 100000);
                    HRegion dilatedRegion1 = selectedRegion1.DilationCircle(8d);
                    HRegion RegionUnion = dilatedRegion1.Union1();
                    HRegion ConnectedRegions3 = RegionUnion.Connection();
                    //求交集
                    HRegion RegionIntersection = ConnectedRegions3.Intersection(selectedRegion1);
                    HRegion SortedRegions = RegionIntersection.SortRegion("character", "true", "row");
                    //加载OMC文件
                    HOCRMlp hOCRMlp = new HOCRMlp();
                    hOCRMlp.ReadOcrClassMlp("charact.omc");
                    //OCR识别
                    HTuple carNumber = hOCRMlp.DoOcrMultiClassMlp(SortedRegions, ImageReduce, out HTuple con);
                    string[] arrary = carNumber.ToSArr();
                    string str = "";
                    for (int i1 = 0; i1 < arrary.Length; i1++)
                    {
                        str += arrary[i1];
                    }
                    this.label4.Text = str;
                    // 清空Halcon窗口内容
                    this.hswc2.HalconWindow.ClearWindow();
                    // 显示旋转校正后的图像
                    this.hswc2.HalconWindow.DispObj(ImageReduce);
                    this.hswc2.SetFullImagePart();
                    return;

                }

            }
            //// 清空Halcon窗口内容
            //this.hswc1.HalconWindow.ClearWindow();
            //// 显示旋转校正后的图像
            //this.hswc1.HalconWindow.DispObj(selectedRegion);

            //this.hswc1.SetFullImagePart();
        }
        // 初始化相机
        private void InitializeCamera()
        {
            try
            {
                // 打开相机（参数需根据相机类型调整）
                _framegrabber = new HFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "default",
                                                  -1, "default", -1, "false", "default",
                                                  "default", 0, -1);

                // 获取 HSmartWindowControl 的 Halcon 窗口句柄
                _hWindow = hswc1.HalconWindow;
            }
            catch (HalconException ex)
            {
                //MessageBox.Show($"相机初始化失败: {ex.Message}");
            }
        }
        // 开始实时采集
        private void StartGrabbing()
        {
            if (_framegrabber == null) InitializeCamera();

            _isGrabbing = true;
            //定义线程，在线程方法进行图像循环采集
            _grabThread = new Thread(GrabLoop);
            _grabThread.IsBackground = true;
            _grabThread.Start();
        }
        // 采集循环（在独立线程中运行）
        private void GrabLoop()
        {
            while (_isGrabbing)
            {
                try
                {
                    // 抓取图像
                    image = _framegrabber.GrabImageAsync(-1);

                    // 在 Halcon 窗口中显示图像
                    _hWindow.DispObj(image);
                    hswc1.SetFullImagePart();
                    image.Dispose();
                }
                catch (HalconException ex)
                {
                    // 处理异常（如相机断开）
                    if (ex.GetErrorCode() == 5302) // 采集超时
                        Thread.Sleep(1000);
                    else
                        break;
                }
            }
        }
        // 停止采集
        private void StopGrabbing()
        {
            _isGrabbing = false;
            _grabThread?.Join(); // 等待线程结束
            _framegrabber?.Dispose();
            _framegrabber = null;
        }
        private void button3_Click(object sender, EventArgs e)
        {
            StartGrabbing();
        }
    }
}
